package com.three.domain.player;

import com.three.api.event.PlayerAttributeChangeEvent;
import com.three.api.protocol.Packet;
import com.three.api.push.PushSender;
import com.three.constant.LanguageId;
import com.three.event.EventBus;
import com.three.protocol.CommandEnum;
import com.three.protocol.PlayerModule;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by mathua on 2017/6/18.
 */
public enum PlayerAttrType {
    GOLD(PlayerModule.PlayerAttr.GOLD, LanguageId.GOLD) {// 金币
        @Override
        public long getAttrValue(PlayerPo player) {
            return player != null ? player.getGold() : 0;
        }

        @Override
        protected void setAttrValue(PlayerPo player, long value) {
            value = Math.max(0, value);
            value = Math.min(getLimit(player), value);
            player.setGold(value);
        }

        @Override
        public long getLimit(PlayerPo player) {
            // TODO 后面可能改成根据玩家等级开放金币上限~
            return PlayerAttrValueLimit.GOLD_MAX_VALUE;
        }
    },
    DIAMOND(PlayerModule.PlayerAttr.DIAMOND, LanguageId.DIAMOND) {// 钻石
        @Override
        public long getAttrValue(PlayerPo player) {
            return player != null ? player.getDiamond() : 0;
        }

        @Override
        protected void setAttrValue(PlayerPo player, long value) {
            value = Math.max(0, value);
            value = Math.min(getLimit(player), value);
            player.setDiamond(value);
        }

        @Override
        public long getLimit(PlayerPo player) {
            // TODO 后面可能改成根据玩家等级开放钻石上限~
            return PlayerAttrValueLimit.DIAMOND_MAX_VALUE;
        }
    },
    ;

    private final PlayerModule.PlayerAttr playerAttr;
    private final long nameId;
    PlayerAttrType(PlayerModule.PlayerAttr playerAttr, long nameId) {
        this.playerAttr = playerAttr;
        this.nameId = nameId;
    }

    /**
     * 属性改变回调
     * @param player 属性的持有者
     * @param oldValue 属性旧值
     * @param latestValue 属性最新值
     * @param isNotify 是否通知客户端
     */
    public void onChanged(PlayerPo player, long oldValue, long latestValue, boolean isNotify) {
        if(oldValue == latestValue){
            return;
        }
        //通知事件总线
        switch (this) {
            case GOLD:
                EventBus.I.post(new PlayerAttributeChangeEvent(player.getPlayerId(), PlayerAttributeChangeEvent.PlayerAttrType.GOLD,oldValue,latestValue));
                break;
            case DIAMOND:
                EventBus.I.post(new PlayerAttributeChangeEvent(player.getPlayerId(), PlayerAttributeChangeEvent.PlayerAttrType.DIAMOND,oldValue,latestValue));
                break;
            default:
                break;
        }
        //下发变更通知
        if(isNotify){
            PlayerModule.NotifyPlayerAttrChange_101.Builder builder = PlayerModule.NotifyPlayerAttrChange_101.newBuilder();
            builder.setPlayerAttr(playerAttr);
            builder.setLatestValue(latestValue);
            Packet packet = Packet.build(CommandEnum.Command.NOTIFY_PLAYER_ATTR_CHANGE, builder.build().toByteArray());
            PushSender sender = PushSender.get();
            sender.send(packet, player.getPlayerId());
        }
    }

    public abstract long getAttrValue(PlayerPo player);
    protected abstract void setAttrValue(PlayerPo player, long value);
    public abstract long getLimit(PlayerPo player);

    private static Map<PlayerModule.PlayerAttr, PlayerAttrType> map = new HashMap<>();
    static {
        for(PlayerAttrType type : values()){
            map.putIfAbsent(type.playerAttr, type);
        }
    }

    public static PlayerAttrType valueOf(int id) {
        PlayerModule.PlayerAttr playerAttr = PlayerModule.PlayerAttr.valueOf(id);
        return map.get(playerAttr);
    }

    interface PlayerAttrValueLimit {
        int GOLD_MAX_VALUE = 20 * 10000 * 10000;
        int DIAMOND_MAX_VALUE = 20 * 10000 * 10000;;
    }

    public long getNameId() {
        return nameId;
    }

    public int getPlayerAttr() {
        return playerAttr.getNumber();
    }
}
